home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ETO Development Tools 4
/
ETO Development Tools 4.iso
/
Tools - Objects
/
MacApp
/
MacApp 3.0a2
/
Libraries
/
UScroller.cp
< prev
next >
Wrap
Text File
|
1991-05-01
|
21KB
|
780 lines
// UScroller.cp
// Copyright © 1987-1991 by Apple Computer Inc. All rights reserved.
#ifndef __UGEOMETRY__
#include <UGeometry.h>
#endif
#ifndef __ULIST__
#include <UList.h>
#endif
#ifndef __UEVENT__
#include <UEvent.h>
#endif
#ifndef __UCOMMAND__
#include <UCommand.h>
#endif
#ifndef __UDOCUMENT__
#include <UDocument.h>
#endif
#ifndef __CONTROLS__
#include <Controls.h>
#endif
#ifndef __UCONTROL__
#include <UControl.h>
#endif
#ifndef __UFAILURE__
#include <UFailure.h>
#endif
#ifndef __UMACAPPUTILITIES__
#include <UMacAppUtilities.h>
#endif
#ifndef __DIALOGS__
#include <Dialogs.h>
#endif
#ifndef __UPATCH__
#include <UPatch.h>
#endif
#ifndef __UMACAPPGLOBALS__
#include <UMacAppGlobals.h>
#endif
#ifndef __STDLIB__
#include "StdLib.h"
#endif
#ifndef __UVIEWSERVER__
#include <UViewServer.h>
#endif
#ifndef __USCROLLER__
#include "UScroller.h"
#endif
//--------------------------------------------------------------------------------------------------
#pragma segment MAOpen
pascal void TScroller::Initialize(void) // override
{
inherited::Initialize();
fConstrain[hSel] = FALSE;
fConstrain[vSel] = FALSE;
fMaxTranslation = gZeroVPt;
fRespondsToFunctionKeys = TRUE;
fSBarOffsets = gZeroVRect;
fScrollBars[hSel] = NULL;
fScrollBars[vSel] = NULL;
fScrollLimit = gZeroVPt;
fScrollUnit = VPoint(kStdScrollUnit, kStdScrollUnit);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAOpen
pascal void TScroller::IScroller(TView* itsSuperView,
const VPoint& itsLocation,
const VPoint& itsSize,
SizeDeterminer itsHSizeDet,
SizeDeterminer itsVSizeDet,
const VPoint& itsMax,
Boolean wantHorzSBar,
Boolean wantVertSBar)
{
TDocument * itsSuperViewsDocument = NULL;
if (itsSuperView)
itsSuperViewsDocument = itsSuperView->fDocument;
this->IView(itsSuperViewsDocument, itsSuperView, itsLocation, itsSize, itsHSizeDet, itsVSizeDet);
this->SetScrollParameters(VPoint(kStdScrollUnit, kStdScrollUnit), FALSE, FALSE);
this->SetScrollLimits(itsMax, kDontRedraw);
if (wantHorzSBar)
this->CreateScrollBar(hSel);
if (wantVertSBar)
this->CreateScrollBar(vSel);
if (wantHorzSBar || wantVertSBar)
this->AdjustScrollBars(kDontInvalidate);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAOpen
pascal void TScroller::IRes(TDocument* itsDocument,
TView* itsSuperView,
Ptr& itsParams)
{
VPoint scrollLimit;
VCoordinate horzUnits;
VCoordinate vertUnits;
Boolean horzConstraint;
Boolean vertConstraint;
Rect sBarOffsets;
Boolean wantHSBar;
Boolean wantVSBar;
inherited::IRes(itsDocument, itsSuperView, itsParams);
{ // Remember: itsParams could be a pointer into a relocatable block!
// So, retrieve the values from the template into locals
// so that we can pass the values into methods that may move memory.
ScrollerTemplate& templateData = *((ScrollerTemplate *) itsParams);
scrollLimit.h = templateData.horzMax;
scrollLimit.v = templateData.vertMax;
horzUnits = templateData.hScrollUnits;
vertUnits = templateData.vScrollUnits;
horzConstraint = templateData.hConstrain;
vertConstraint = templateData.vConstrain;
sBarOffsets = templateData.sBarOffsets;
wantHSBar = templateData.wantHSBar;
wantVSBar = templateData.wantVSBar;
}
this->SetScrollLimits(scrollLimit, kDontRedraw);
this->SetScrollParameters(VPoint(vertUnits, horzUnits), horzConstraint, vertConstraint);
fSBarOffsets = sBarOffsets;
if (wantHSBar)
this->CreateTemplateScrollBar(hSel);
if (wantVSBar)
this->CreateTemplateScrollBar(vSel);
if (wantHSBar || wantVSBar)
this->AdjustScrollBars(kDontInvalidate);
OffsetPtr(itsParams, sizeof(ScrollerTemplate));
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScrollerRes
pascal TObject* TScroller::Clone(void) // override
{
TScroller * aClonedScroller;
aClonedScroller = (TScroller *)(inherited::Clone());
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
{
if (aClonedScroller->fScrollBars[vhs])
{
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
TScrollerScrollBar *temp = (TScrollerScrollBar *)(aClonedScroller->fScrollBars[vhs]->Clone());
aClonedScroller->fScrollBars[vhs] = temp;
aClonedScroller->fScrollBars[vhs]->AttachScroller(this);
}
}
return aClonedScroller;
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAWriteRes
pascal void TScroller::WRes(ViewRsrcHandle theResource,
Ptr& itsParams) // override
{
ScrollerTemplatePtr scPtr;
VRect aVRect;
inherited::WRes(theResource, itsParams);
scPtr = (ScrollerTemplatePtr)(ExpandPtr((Handle)theResource, itsParams, sizeof(ScrollerTemplate)));
scPtr->wantHSBar = (fScrollBars[hSel] != NULL);
scPtr->wantVSBar = (fScrollBars[vSel] != NULL);
scPtr->vertMax = fScrollLimit.v;
scPtr->horzMax = fScrollLimit.h;
scPtr->vScrollUnits = (short)fScrollUnit.v;
scPtr->hScrollUnits = (short)fScrollUnit.h;
scPtr->vConstrain = fConstrain[vSel];
scPtr->hConstrain = fConstrain[hSel];
aVRect = fSBarOffsets;
scPtr->sBarOffsets = aVRect;
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAWriteRes
pascal void TScroller::WriteRes(ViewRsrcHandle theResource,
Ptr& itsParams) // override
{
gWResSignature = 'scrl';
gWResType = "TScroller";
this->WRes(theResource, itsParams);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAClose
pascal void TScroller::Free(void) // override
{
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
TScrollerScrollBar *temp = (TScrollerScrollBar *)(FreeIfObject(fScrollBars[hSel]));
fScrollBars[hSel] = temp;
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
temp = (TScrollerScrollBar *)(FreeIfObject(fScrollBars[vSel]));
fScrollBars[vSel] = temp;
inherited::Free();
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAOpen
pascal void TScroller::AddSubView(TView* theSubView)// override
{
inherited::AddSubView(theSubView);
theSubView->BeInScroller(this);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::AdjustScrollBars(Boolean invalidate)
{
TScrollBar * aScrollBar;
VHSelect ortho;
VPoint loc;
VPoint size;
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
{
aScrollBar = fScrollBars[vhs];
if (aScrollBar)
{
ortho = gOrthogonal[vhs];
loc = fLocation;
size = fSize;
loc[vhs] += fSBarOffsets[topLeft][vhs] - 1;
loc[ortho] += size[ortho];
size[vhs] = size[vhs] - fSBarOffsets[topLeft][vhs] + fSBarOffsets[botRight][vhs] + 2;
size[ortho] = kSBarSize;
aScrollBar->Resize(size, invalidate);
aScrollBar->Locate(loc, invalidate);
}
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment MADoCommand
pascal VCoordinate ProportionalScroll(VCoordinate diff,
VPoint scrollUnit,
VCoordinate maxTranslationchange,
VHSelect vhs)
{
if (scrollUnit[vhs] != 0)
return MinMax(scrollUnit[vhs], IntMultiply((short)(((short)diff + ((short)scrollUnit[vhs] / 2)) / scrollUnit[vhs]), (short)scrollUnit[vhs]), maxTranslationchange);
else
return scrollUnit[vhs];
}
pascal void TScroller::AutoScroll(const VPoint& viewPt,
VPoint& delta)
{
VRect myExtent;
delta = gZeroVPt;
this->GetExtent(myExtent);
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
if (viewPt[vhs] < myExtent[topLeft][vhs])
{
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
VCoordinate temp = -ProportionalScroll(myExtent[topLeft][vhs] - viewPt[vhs], fScrollUnit, fTranslation[vhs], vhs);
delta[vhs] = temp;
}
else if (viewPt[vhs] > myExtent[botRight][vhs])
{
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
VCoordinate temp1 = ProportionalScroll(viewPt[vhs] - myExtent[botRight][vhs], fScrollUnit, fMaxTranslation[vhs] - fTranslation[vhs], vhs);
delta[vhs] = temp1;
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAOpen
pascal void TScroller::CreateTemplateScrollBar(VHSelect itsDirection)
{
TScrollerScrollBar * aScrollerScrollBar;
FailInfo fi;
if (fi.Try())
{
aScrollerScrollBar = (TScrollerScrollBar *)(gViewServer->DoCreateViews(fDocument, fSuperView, kScrollBarId, gZeroVPt));
aScrollerScrollBar->fDirection = itsDirection;/* !!!Unfortunately this is not part of the
resource */
aScrollerScrollBar->fShown = fShown; // Only wants to show if we want to show
aScrollerScrollBar->AttachScroller(this);
fi.Success();
}
else // Recover
{
this->Free();
fi.ReSignal();
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAOpen
pascal void TScroller::CreateScrollBar(VHSelect itsDirection)
{
TScrollerScrollBar * aScrollerScrollBar;
FailInfo fi;
if (fi.Try())
{
aScrollerScrollBar = new TScrollerScrollBar;
aScrollerScrollBar->IScrollerScrollBar(fSuperView, gZeroVPt, gZeroVPt, sizeVariable, sizeVariable, itsDirection, fMaxTranslation[itsDirection], this);
fi.Success();
}
else // Recover
{
this->Free();
fi.ReSignal();
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void DoPageScroll(short partCode, TScroller* aScroller)
{
if (aScroller && aScroller->fScrollBars[vSel])
{
aScroller->fScrollBars[vSel]->DeltaValue(VCoordinate(aScroller->ScrollStep(vSel, partCode)));
}
aScroller->Update();
}
#pragma segment MAScroll
pascal void TScroller::DoKeyCommand(TToolboxEvent* event)// override
{
if (this->IsEnabled() && fRespondsToFunctionKeys)
switch (event->fCharacter)
{
case chPageUp:
DoPageScroll(inPageUp, this);
break;
case chPageDown:
DoPageScroll(inPageDown, this);
break;
case chHome:
this->ScrollTo(gZeroVPt, kRedraw);
this->Update();
break;
case chEnd:
this->ScrollTo(fMaxTranslation, kRedraw);
this->Update();
break;
default:
inherited::DoKeyCommand(event);
break;
}
else
inherited::DoKeyCommand(event);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void TScroller::DoScroll(const VPoint& delta,
Boolean redraw)
{
VPoint localDelta(delta);
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
{
if (localDelta[vhs] < 0)
{
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
long temp = Max(localDelta[vhs], -fTranslation[vhs]);
localDelta[vhs] = temp;
}
else if (localDelta[vhs] > 0)
{
// !!!FIX the following 2 lines after MPW C compiler bug is corrected.
long temp1 = Min(localDelta[vhs], (fMaxTranslation[vhs] - fTranslation[vhs]));
localDelta[vhs] = temp1;
}
fTranslation[vhs] += localDelta[vhs];
}
if (localDelta != gZeroVPt)
{
this->InvalidateFocus();
this->UpdateCoordinates();
// !!! In the future the decision will be made differently as to how to render
if (redraw)
this->ScrollDraw(localDelta, kInvalidate);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment BBFields
pascal void TScroller::Fields(TObject* obj) // override
{
obj->DoToField("TScroller", (Ptr)NULL, bClass);
obj->DoToField("fScrollLimit", (Ptr) & fScrollLimit, bVPoint);
obj->DoToField("fMaxTranslation", (Ptr) & fMaxTranslation, bVPoint);
obj->DoToField("fScrollBars[vSel]", (Ptr) & fScrollBars[vSel], bObject);
obj->DoToField("fScrollBars[hSel]", (Ptr) & fScrollBars[hSel], bObject);
obj->DoToField("fScrollUnit", (Ptr) & fScrollUnit, bPoint);
obj->DoToField("fSBarOffsets", (Ptr) & fSBarOffsets, bVRect);
obj->DoToField("fConstrain[hSel]", (Ptr) & fConstrain[hSel], bBoolean);
obj->DoToField("fConstrain[vSel]", (Ptr) & fConstrain[vSel], bBoolean);
obj->DoToField("fRespondsToFunctionKeys", (Ptr) & fRespondsToFunctionKeys, bBoolean);
inherited::Fields(obj);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScrollerRes
pascal void TScroller::ForceRedraw(void) // override
{
inherited::ForceRedraw();
if (fScrollBars[hSel])
fScrollBars[hSel]->ForceRedraw();
if (fScrollBars[vSel])
fScrollBars[vSel]->ForceRedraw();
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScrollerRes
pascal TScroller* TScroller::GetScroller(Boolean)
{
return this;
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScrollerRes
pascal void TScroller::HaveScrollBar(TScrollerScrollBar* theScrollBar,
VHSelect direction)
{
#if qDebug
if ((theScrollBar) && (theScrollBar->fDirection != direction))
ProgramBreak("Scroll bar is wrong direction.");
#endif
fScrollBars[direction] = theScrollBar;
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::Locate(const VPoint& newLoc,
Boolean invalidate)// override
{
inherited::Locate(newLoc, invalidate);
this->AdjustScrollBars(invalidate);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::RemoveSubView(TView* theSubView)// override
{
theSubView->BeInScroller(NULL);
inherited::RemoveSubView(theSubView);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::Resize(const VPoint& newSize,
Boolean invalidate)// override
{
Boolean sBarWasVisible[2];
// If the scroll bars are visible, erase them now so that they aren't temporarily
// displayed in the wrong place.
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
{
if ((fScrollBars[vhs] != NULL) && (fScrollBars[vhs]->Focus()) && (fScrollBars[vhs]->IsCMgrVisible()))
{
sBarWasVisible[vhs] = TRUE;
if (!invalidate)
HideControl((fScrollBars[vhs])->fCMgrControl);
else
fScrollBars[vhs]->SetCMgrVisibility(FALSE);
}
else
sBarWasVisible[vhs] = FALSE;
}
inherited::Resize(newSize, invalidate);
this->AdjustScrollBars(invalidate);
this->SetScrollLimits(fScrollLimit.Copy(), kDontRedraw); // Readjust sbar maximums and fMaxTranslation
for (vhs = vSel; vhs <= hSel; ++vhs)
if (sBarWasVisible[vhs])
fScrollBars[vhs]->SetCMgrVisibility(TRUE);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void TScroller::RevealRect(const VRect& rectToReveal,
const VPoint& minToSee,
Boolean redraw)// override
{
VRect myExtent;
VCoordinate minAmt;
VCoordinate coord;
VPoint delta;
this->GetExtent(myExtent);
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
{
minAmt = Min(myExtent.Length(vhs), minToSee[vhs]);
coord = rectToReveal[topLeft][vhs] + minAmt - myExtent[botRight][vhs];
if (coord <= 0)
coord = Min(0, rectToReveal[botRight][vhs] - minAmt - myExtent[topLeft][vhs]);
delta[vhs] = coord;
}
this->ScrollBy(delta, redraw);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void TScroller::ScrollBy(const VPoint& delta,
Boolean redraw)
{
if (delta != gZeroVPt)
{
if (fScrollBars[vSel])
fScrollBars[vSel]->DeltaValue(delta.v);
if (fScrollBars[hSel])
fScrollBars[hSel]->DeltaValue(delta.h);
this->DoScroll(delta, redraw);
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void TScroller::ScrollDraw(const VPoint& delta,
Boolean invalidate)
{
Rect visRect;
if (this->Focus())
{
this->GetDrawableQDRect(visRect);
if (gIntenseDebugging)
WriteFocus();
if (!visRect.Empty())
{
if ((labs(delta.h) > kMaxCoord) || (labs(delta.v) > kMaxCoord))// too far to scrollrect
this->InvalidateRect(visRect);
else
{
#if qDebug
UseTempRgn2("TScroller.ScrollDraw");
#endif
ScrollRect(visRect, (short)(-delta.h), (short)(-delta.v), gTempRgn2);
this->InvalidateRgn(gTempRgn2);
#if qDebug
DoneWithTempRgn2();
#endif
}
if (!invalidate)
this->Update();
// ??? EndUpdate(thePort);
}
}
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal VCoordinate TScroller::ScrollRelative(VHSelect vhs,
VCoordinate sBarValue)
{
VPoint pixelDelta = gZeroVPt;
VCoordinate newValue;
if ((fConstrain[vhs] && (sBarValue != fMaxTranslation[vhs])))
newValue = (sBarValue + fScrollUnit[vhs] / 2) / fScrollUnit[vhs] * fScrollUnit[vhs];
else
newValue = sBarValue;
pixelDelta[vhs] = newValue - fTranslation[vhs];
this->DoScroll(pixelDelta, kRedraw);
return (newValue - sBarValue);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal VCoordinate TScroller::ScrollStep(VHSelect vhs,
short partCode)
{
short scrollUnit = (short)fScrollUnit[vhs];
VCoordinate delta;
VCoordinate adjustment;
VPoint deltaPt = gZeroVPt;
switch (partCode)
{
case inUpButton:
case inDownButton:
delta = scrollUnit;
break;
case inPageUp:
case inPageDown:
delta = fSize[vhs];
break;
#if qDebug
default:
{
Str255 theString;
ConcatNumber("TScroller::ScrollStep: bad part code =", partCode, theString);
ProgramBreak(theString);
break;
}
#endif
}
if ((partCode == inUpButton) || (partCode == inPageUp))
delta = -delta;
// Constrain if necessary
if (fConstrain[vhs] && (scrollUnit != 0))
{
adjustment = (Max(0, fTranslation[vhs] + delta)) % scrollUnit;
if (adjustment != 0)
if (delta > 0)
delta -= adjustment;
else
delta += (scrollUnit - adjustment);
}
deltaPt[vhs] = delta;
this->DoScroll(deltaPt, kRedraw);
return delta;
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void TScroller::ScrollTo(const VPoint& scrollLoc,
Boolean redraw)
{
this->SetLocalOrigin(scrollLoc, redraw);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MAScroll
pascal void TScroller::SetLocalOrigin(const VPoint& newOrigin,
Boolean redraw)
{
this->ScrollBy(newOrigin - fTranslation, redraw);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::SetScrollLimits(const VPoint& scrollLimit,
Boolean drawScrollBars)
{
VPoint newTranslation(fTranslation);
fScrollLimit = scrollLimit;
for (VHSelect vhs = vSel; vhs <= hSel; ++vhs)
{
VCoordinate maxCoord = Max(0, scrollLimit[vhs] - fSize[vhs]);
if (maxCoord != fMaxTranslation[vhs])
{
fMaxTranslation[vhs] = maxCoord;
if (fScrollBars[vhs])
fScrollBars[vhs]->SetLongMax(maxCoord, drawScrollBars);
if (maxCoord < fTranslation[vhs])
newTranslation[vhs] = maxCoord;
}
}
if (newTranslation != fTranslation)
this->ScrollTo(newTranslation, kRedraw);
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::SetScrollParameters(const VPoint& units,
Boolean horzConstraint,
Boolean vertConstraint)
{
fScrollUnit = units;
fConstrain[hSel] = horzConstraint;
fConstrain[vSel] = vertConstraint;
}
//--------------------------------------------------------------------------------------------------
#pragma segment MANonRes
pascal void TScroller::SubViewChangedSize(TView* ,
const VPoint&)// override
{
VPoint aVPoint = gZeroVPt;
CSubViewIterator iter(this);
for(TView* theSubView = iter.FirstSubView(); iter.More(); theSubView = iter.NextSubView())
{
aVPoint.v = Max(aVPoint.v, theSubView->fLocation.v + theSubView->fSize.v);
aVPoint.h = Max(aVPoint.h, theSubView->fLocation.h + theSubView->fSize.h);
}
this->SetScrollLimits(aVPoint, kRedraw);
}